/*
 * 宠物管理系统主类，包含数据存储结构和核心功能入口
 * 提供宠物信息管理、主人信息管理、医疗记录管理和统计查询功能
 *
 * - pets: 存储所有宠物对象的ArrayList
 * - owners: 存储主人信息的HashMap（key: ownerId）
 * - medicalRecords: 存储医疗记录的LinkedList

 */
package animal;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;

/**
 * 宠物管理系统主类，包含系统核心功能和主菜单循环
 * 提供5大功能模块入口：
 * 1-3 分别处理宠物/主人/医疗记录的CRUD操作
 * 4 提供统计分析功能
 * 0 退出系统
 */
public class PetManagementSystem {
    // 存储介质定义
    private static List<Pet> pets = new ArrayList<>();  ///宠物集合
    private static Map<String, Owner> owners = new HashMap<>();  ///主人集合
    private static List<MedicalRecord> medicalRecords = new LinkedList<>(); //医疗记录集合

    static {  /// 初始化一些主人
        owners.put("o101", new Owner("o101", "张三", "17788994455", "上海市外滩"));
        owners.put("o102", new Owner("o102", "李四", "09999999999", "北京市海淀区"));
        owners.put("o103", new Owner("o103", "王五", "10099885166", "昌吉市融投"));
    }

    /**
     * 系统主菜单循环
     * 提供5大功能模块选择：
     * 1-3 分别处理宠物/主人/医疗记录的CRUD操作
     * 4 提供统计分析功能
     * 0 退出系统
     *
     */
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        while (true) {
            System.out.print("输入姓名：(-1 退出)");
            String name = scanner.next();
            if (name.equals("-1")) return;
            System.out.print("输入密码：");
            String password = scanner.next();

            if (name.equals("张三") && password.equals("123456")) {
                scanner.nextLine();
                break;
            }

            System.out.println("登陆失败，重新登陆");
        }

        while (true) {  /// 一级菜单
            System.out.println("宠物管理系统");
            System.out.println("1. 宠物信息管理");
            System.out.println("2. 主人信息管理");
            System.out.println("3. 医疗记录管理");
            System.out.println("4. 统计查询");
            System.out.println("0. 退出系统");
            System.out.print("请选择操作(0-4): ");

            try {
                int choice = Integer.parseInt(scanner.nextLine());
                switch (choice) {
                    case 1:  ///管理宠物菜单
                        petManagementMenu(scanner);
                        break;
                    case 2:  ///管理主人菜单
                        ownerManagementMenu(scanner);
                        break;
                    case 3:  ///管理医疗记录菜单
                        medicalRecordMenu(scanner);
                        break;
                    case 4:  ///统计菜单
                        statisticsMenu(scanner);
                        break;
                    case 0:
                        System.out.println("感谢使用，系统退出");
                        return;
                    default:
                        System.out.println("错误：请输入0-4之间的数字");
                }
            } catch (NumberFormatException e) {
                System.out.println("错误：请输入有效的数字选项");
            }
        }
    }

    /**
     * 宠物信息管理子菜单
     * 提供CRUD操作选项：
     * 1-4 分别对应新增/编辑/删除/查询操作
     * 0 返回主菜单
     *
     * @param scanner 输入流扫描器
     */
    private static void petManagementMenu(Scanner scanner) {
        while (true) {
            System.out.println("\n宠物信息管理");
            System.out.println("1. 新增宠物");
            System.out.println("2. 编辑宠物");
            System.out.println("3. 删除宠物");
            System.out.println("4. 查询宠物");
            System.out.println("0. 返回主菜单");
            System.out.print("请选择操作(0-4): ");

            try {
                int choice = Integer.parseInt(scanner.nextLine());
                switch (choice) {
                    case 1: ///新增宠物
                        addPet(scanner);
                        break;
                    case 2: ///修改宠物
                        updatePet(scanner);
                        break;
                    case 3: ///删除宠物
                        deletePet(scanner);
                        break;
                    case 4:  ///查询宠物
                        queryPets(scanner);
                        break;
                    case 0:
                        return;
                    default:
                        System.out.println("错误：请输入0-4之间的数字");
                }
            } catch (NumberFormatException e) {
                System.out.println("错误：请输入有效的数字选项");
            }
        }
    }

    /**
     * 新增宠物记录
     * 验证输入数据格式和关联对象存在性，包含以下验证步骤：
     * 1. 宠物ID格式验证（P+3位数字）
     * 2. 主人ID格式验证（O+3位数字）
     * 3. 主人存在性验证
     * 4. 年龄格式异常捕获
     *
     * @param scanner 输入流扫描器
     */
    private static void addPet(Scanner scanner) {
        try {
            System.out.print("输入宠物ID(pXXX): ");
            String petId = scanner.nextLine();
            if (!isValidPetId(petId)) {
                throw new IllegalArgumentException("宠物ID格式错误，应为p+3位数字");
            }

            System.out.print("输入宠物姓名: ");
            String name = scanner.nextLine();

            System.out.print("输入品种: ");
            String breed = scanner.nextLine();

            System.out.print("输入年龄: ");
            int age = Integer.parseInt(scanner.nextLine());

            System.out.print("输入主人ID(oXXX): ");
            String ownerId = scanner.nextLine();

            if (!isValidOwnerId(ownerId)) {
                throw new IllegalArgumentException("主人ID格式错误，应为O+3位数字");
            }

            /// 验证是否有这个主人
            if (!owners.containsKey(ownerId)) {
                throw new IllegalArgumentException("错误：主人" + ownerId + "不存在");
            }

            /// 全通过后添加
            pets.add(new Pet(petId, name, breed, age, ownerId));
            System.out.println("添加成功");

            /// 捕获相应的异常
        } catch (NumberFormatException e) {
            System.out.println("错误：年龄必须为数字");
        } catch (IllegalArgumentException e) {
            System.out.println(e.getMessage());
        }
    }

    /**
     * 编辑现有宠物信息
     * 支持修改姓名、品种和年龄字段，包含以下验证：
     * 1. 宠物存在性验证
     * 2. 年龄格式异常捕获
     *
     * @param scanner 输入流扫描器
     */
    private static void updatePet(Scanner scanner) {
        System.out.print("输入要修改的宠物ID: ");
        String petId = scanner.nextLine();

        /// 查找有没有对应的宠物，如果不在就返回上一级
        Pet pet = findPetById(petId);
        if (pet == null) {
            System.out.println("错误：宠物不存在");
            return;
        }
        /// 如果有则继续
        System.out.print("输入新姓名(当前: " + pet.getName() + "): ");
        String name = scanner.nextLine();
        System.out.print("输入新品种(当前: " + pet.getBreed() + "): ");
        String breed = scanner.nextLine();
        System.out.print("输入新年龄(当前: " + pet.getAge() + "): ");
        int age = Integer.parseInt(scanner.nextLine());

        /// 修改属性
        pet.setName(name);
        pet.setBreed(breed);
        pet.setAge(age);

        System.out.println("修改成功：宠物" + petId + "信息已更新");
    }

    /**
     * 删除宠物记录
     * 删除前执行完整性检查，包含以下验证：
     * 1. 宠物存在性验证
     * 2. 关联医疗记录检查
     *
     * @param scanner 输入流扫描器
     */
    private static void deletePet(Scanner scanner) {
        System.out.print("输入宠物ID: ");
        String petId = scanner.nextLine();

        /// 通过id遍历所有宠物，找到就删除
        Iterator<Pet> iterator = pets.iterator(); ///迭代器
        while (iterator.hasNext()) {
            ///先从集合中取出一个宠物，将宠物的id跟输入的id对比，如果一样就删除
            Pet pet = iterator.next();
            if (pet.getPetId().equals(petId)) {
                iterator.remove();
                System.out.println("删除成功");
                return;
            }
        }

        System.out.println("错误：宠物不存在");
    }

    /**
     * 宠物信息查询
     * 支持模糊查询功能，搜索字段包含：
     * 1. 宠物ID
     * 2. 宠物姓名
     * 3. 主人ID
     *
     * @param scanner 输入流扫描器
     */
    private static void queryPets(Scanner scanner) {
        System.out.print("输入查询条件(空表示查询全部):(PetId/name/OwnerId) ");
        /// 将输入的查询条件改成小写方便比较
        String keyword = scanner.nextLine().toLowerCase();
        /// 一个一个遍历，如果输入的条件只要包含在 宠物id，name，主人id 其中之一就可以加入到查询队列
        List<Pet> results = new ArrayList<>();
        for (Pet pet : pets) {
            if (pet.getPetId().toLowerCase().contains(keyword) ||
                    pet.getName().toLowerCase().contains(keyword) ||
                    pet.getOwnerId().toLowerCase().contains(keyword)) {
                results.add(pet); ///加入到查询队列
            }
        }

        if (results.isEmpty()) {
            System.out.println("未找到匹配结果");
        } else { /// 如果查询队列有数据就展示
            System.out.println("匹配结果:");
            System.out.println();
            for (Pet pet : results) {
                System.out.println(pet);
            }
        }
    }

    /**
     * 主人信息管理子菜单
     * 提供CRUD操作选项：
     * 1-4 分别对应新增/编辑/删除/查询操作
     * 0 返回主菜单
     *
     * @param scanner 输入流扫描器
     */
    private static void ownerManagementMenu(Scanner scanner) {
        while (true) {
            System.out.println("\n主人信息管理");
            System.out.println("1. 新增主人");
            System.out.println("2. 编辑主人");
            System.out.println("3. 删除主人");
            System.out.println("4. 查询主人");
            System.out.println("0. 返回主菜单");
            System.out.print("请选择操作(0-4): ");

            try {
                int choice = Integer.parseInt(scanner.nextLine());
                switch (choice) {
                    case 1:
                        addOwner(scanner);
                        break;
                    case 2:
                        updateOwner(scanner);
                        break;
                    case 3:
                        deleteOwner(scanner);
                        break;
                    case 4:
                        queryOwners(scanner);
                        break;
                    case 0:
                        return;
                    default:
                        System.out.println("错误：请输入0-4之间的数字");
                }
            } catch (NumberFormatException e) {
                System.out.println("错误：请输入有效的数字选项");
            }
        }
    }

    /**
     * 新增主人记录
     * 验证输入数据格式和唯一性约束，包含以下验证：
     * 1. 主人ID格式验证（O+3位数字）
     * 2. 主人唯一性验证
     * 3. 电话号码格式验证（11位数字）
     *
     * @param scanner 输入流扫描器
     */
    private static void addOwner(Scanner scanner) {
        try {
            System.out.print("输入主人ID(oXXX): ");
            String ownerId = scanner.nextLine();
            if (!isValidOwnerId(ownerId)) {  /// 检查主人id是否合法
                throw new IllegalArgumentException("主人ID格式错误，应为o+3位数字");
            }
            /// /判断输入的主人ID是否已经存在于owners集合中。如有就不加入
            if (owners.containsKey(ownerId)) {
                throw new IllegalArgumentException("错误：主人" + ownerId + "已存在");
            }

            System.out.print("输入姓名: ");
            String name = scanner.nextLine();

            System.out.print("输入电话(11位数字): ");
            String phone = scanner.nextLine();
            if (!isValidPhone(phone)) {  /// 判断是否合法
                throw new IllegalArgumentException("电话号码必须为11位数字");
            }

            System.out.print("输入地址: ");
            String address = scanner.nextLine();
            /// 如果都顺利就将主人加到集合中，方便管理
            owners.put(ownerId, new Owner(ownerId, name, phone, address));
            System.out.println("添加成功");

        } catch (IllegalArgumentException e) {
            System.out.println(e.getMessage());
        }
    }

    /**
     * 编辑现有主人信息
     * 支持修改所有字段，包含以下验证：
     * 1. 主人存在性验证
     * 2. 电话号码格式验证（11位数字）
     *
     * @param scanner 输入流扫描器
     */
    private static void updateOwner(Scanner scanner) {
        System.out.print("输入要修改的主人ID: ");
        String ownerId = scanner.nextLine();
        /// 根据id取出集合中的对象，如果没有就返回
        Owner owner = owners.get(ownerId);
        if (owner == null) {
            System.out.println("错误：主人不存在");
            return;
        }
        /// 修改的数据
        System.out.print("输入新姓名(当前: " + owner.getName() + "): ");
        String name = scanner.nextLine();

        System.out.print("输入新电话(当前: " + owner.getPhone() + ", 11位数字): ");
        String phone = scanner.nextLine();
        if (!isValidPhone(phone)) {
            System.out.println("错误：电话号码必须为11位数字");
            return;
        }

        System.out.print("输入新地址(当前: " + owner.getAddress() + "): ");
        String address = scanner.nextLine();
        /// 就改成新数据
        owner.setName(name);
        owner.setPhone(phone);
        owner.setAddress(address);

        System.out.println("修改成功：主人" + ownerId + "信息已更新");
    }

    /**
     * 删除主人记录
     * 删除前执行完整性检查，包含以下验证：
     * 1. 主人存在性验证
     * 2. 关联宠物检查
     *
     * @param scanner 输入流扫描器
     */
    private static void deleteOwner(Scanner scanner) {
        System.out.print("输入主人ID: ");
        String ownerId = scanner.nextLine();

        if (!owners.containsKey(ownerId)) {
            System.out.println("错误：主人不存在");
            return;
        }

        /// 检查是否有宠物关联，如果有就不删除，直到将名下的宠物删除或改主人
        for (Pet pet : pets) {
            if (pet.getOwnerId().equals(ownerId)) {
                System.out.println("错误：存在关联宠物，请先处理宠物");
                return;
            }
        }
        /// 删除
        owners.remove(ownerId);
        System.out.println("删除成功");
    }

    /**
     * 主人信息查询
     * 支持模糊查询功能，搜索字段包含：
     * 1. 主人ID
     * 2. 姓名
     * 3. 电话号码
     *
     * @param scanner 输入流扫描器
     */
    private static void queryOwners(Scanner scanner) {
        System.out.print("输入查询条件(空表示查询全部): ");
        /// 将条件改成小写方便比较
        String keyword = scanner.nextLine().toLowerCase();
        /// 如果id，name，电话中只要有一个符合，就直接放入查询队列
        List<Owner> results = new ArrayList<>();
        for (Owner owner : owners.values()) {
            if (owner.getOwnerId().toLowerCase().contains(keyword) ||
                    owner.getName().toLowerCase().contains(keyword) ||
                    owner.getPhone().toLowerCase().contains(keyword)) {
                results.add(owner);
            }
        }

        if (results.isEmpty()) {
            System.out.println("未找到匹配结果");
        } else {  /// 输出队列中的数据
            System.out.println("匹配结果:");
            for (Owner owner : results) {
                System.out.println(owner);
            }
        }
    }

    /**
     * 医疗记录管理子菜单
     * 提供基础功能选项：
     * 1 新增记录
     * 2 查询记录
     * 0 返回主菜单
     *
     * @param scanner 输入流扫描器
     */
    private static void medicalRecordMenu(Scanner scanner) {
        while (true) {
            System.out.println("\n医疗记录管理");
            System.out.println("1. 新增记录");
            System.out.println("2. 查询记录");
            System.out.println("0. 返回主菜单");
            System.out.print("请选择操作(0-2): ");

            try {
                int choice = Integer.parseInt(scanner.nextLine());
                switch (choice) {
                    case 1:  ///添加记录
                        addMedicalRecord(scanner);
                        break;
                    case 2:  ///查询记录
                        queryMedicalRecords(scanner);
                        break;
                    case 0:
                        return;
                    default:
                        System.out.println("错误：请输入0-2之间的数字");
                }
            } catch (NumberFormatException e) {
                System.out.println("错误：请输入有效的数字选项");
            }
        }
    }

    /**
     * 新增医疗记录
     * 验证输入数据格式和关联对象存在性，包含以下验证：
     * 1. 宠物存在性验证
     * 2. 记录ID格式验证（m+3位数字）
     * 3. 日期格式解析（支持YYYY-MM-DD或YYYY-M-d）
     *
     * @param scanner 输入流扫描器
     */
    private static void addMedicalRecord(Scanner scanner) {
        try {
            System.out.print("输入宠物ID: ");
            String petId = scanner.nextLine();
            /// 将宠物id放入到findPetById方法中，如果未找到就返回
            if (findPetById(petId) == null) {
                throw new IllegalArgumentException("错误：宠物不存在");
            }

            System.out.print("输入记录ID(mXXX): ");
            String recordId = scanner.nextLine();
            /// 如果记录id补合法就返回
            if (!recordId.matches("m\\d{3}")) {
                throw new IllegalArgumentException("记录ID格式错误，应为m+3位数字");
            }

            System.out.print("输入类型(疫苗/就诊等): ");
            String type = scanner.nextLine();

            LocalDate date = null;
            try {
                System.out.print("输入日期(格式：YYYY-MM-DD 或 YYYY-M-d): ");
                /// 使用灵活的日期解析格式
                date = LocalDate.parse(scanner.nextLine(), DateTimeFormatter.ofPattern("yyyy-M-d"));
            } catch (Exception e) {
                System.out.println("时间格式不对，请重新操作");
                return;
            }

            System.out.print("输入描述: ");
            String description = scanner.nextLine();
            /// 如果都顺利，就添加到医疗记录集合
            medicalRecords.add(new MedicalRecord(recordId, petId, type, date, description));
            System.out.println("记录添加成功（" + recordId + ")");

        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    /**
     * 查询医疗记录
     * 支持按时间范围过滤，包含以下验证：
     * 1. 宠物存在性验证
     * 2. 日期格式解析（支持YYYY-MM-DD或YYYY-M-d）
     *
     * @param scanner 输入流扫描器
     */
    private static void queryMedicalRecords(Scanner scanner) {
        System.out.print("输入宠物ID: ");
        String petId = scanner.nextLine();

        System.out.println("输入时间范围（格式：YYYY-MM-DD 或 YYYY-M-d）");
        LocalDate startDate = null;
        LocalDate endDate = null;
        try {
            System.out.print("开始日期: ");
            /// 使用灵活的日期解析格式
            startDate = LocalDate.parse(scanner.nextLine(), DateTimeFormatter.ofPattern("yyyy-M-d"));
            System.out.print("结束日期: ");
            endDate = LocalDate.parse(scanner.nextLine(), DateTimeFormatter.ofPattern("yyyy-M-d"));
        } catch (DateTimeParseException e) {
            System.out.println("日期格式错误，请重新操作！");
            return;
        }

        List<MedicalRecord> results = new ArrayList<>();
        /// 遍历每一个记录，获取id对比成功且时间不早于开始时间且不晚于结束时间的加入到查询队列
        for (MedicalRecord record : medicalRecords) {
            if (record.getPetId().equals(petId) &&
                    !record.getDate().isBefore(startDate) &&
                    !record.getDate().isAfter(endDate)) {
                results.add(record);  ///加入到队列
            }
        }

        if (results.isEmpty()) {
            System.out.println("未找到匹配的医疗记录");
        } else {  /// 输出匹配的数据
            System.out.println("匹配结果:");
            for (MedicalRecord record : results) {
                System.out.println(record);
            }
        }
    }

    /**
     * 统计查询子菜单
     * 提供两种统计功能：
     * 1 主人宠物统计
     * 2 未接种疫苗提醒
     * 0 返回主菜单
     *
     * @param scanner 输入流扫描器
     */
    private static void statisticsMenu(Scanner scanner) {
        while (true) {
            System.out.println("\n统计查询");
            System.out.println("1. 主人宠物统计");
            System.out.println("2. 未接种疫苗提醒");
            System.out.println("0. 返回主菜单");
            System.out.print("请选择操作(0-2): ");

            try {
                int choice = Integer.parseInt(scanner.nextLine());
                switch (choice) {
                    case 1:  ///主人宠物统计
                        ownerPetStatistics(scanner);
                        break;
                    case 2:  ///未接种疫苗统计
                        unvaccinatedPetsAlert(scanner);
                        break;
                    case 0:
                        return;
                    default:
                        System.out.println("错误：请输入0-2之间的数字");
                }
            } catch (NumberFormatException e) {
                System.out.println("错误：请输入有效的数字选项");
            }
        }
    }

    /**
     * 主人宠物统计
     * 统计指定主人名下的所有宠物，包含以下验证：
     * 1. 主人存在性验证
     *
     * @param scanner 输入流扫描器
     */
    private static void ownerPetStatistics(Scanner scanner) {
        System.out.print("输入主人ID: ");
        String ownerId = scanner.nextLine();
        /// 如果主人没有，宠物也没有，返回
        if (!owners.containsKey(ownerId)) {
            System.out.println("错误：主人不存在");
            return;
        }
        ///如果主人存在 就一个一个遍历宠物集合中每一个宠物的主人id，如果找到就接入ownerPets队列
        List<Pet> ownerPets = new ArrayList<>();
        for (Pet pet : pets) {
            if (pet.getOwnerId().equals(ownerId)) {
                ownerPets.add(pet);
            }
        }

        System.out.println("主人" + ownerId + "共有" + ownerPets.size() + "只宠物：");
        /// 遍历宠物集合，如果宠物的主人id = 输入的id，就加到查询队列
        List<Pet> results = new ArrayList<>();
        for (Pet pet : pets) {
            if (pet.getOwnerId().equals(ownerId)) {
                results.add(pet); ///加入到查询队列
            }
        }
        /// 如果队列不为空，就输出对应宠物
        if (!results.isEmpty()) {
            System.out.println("匹配结果:");
            for (Pet pet : results) {
                System.out.println(pet);
            }

        }

    }

    /**
     * 未接种疫苗提醒
     * 统计所有未接种疫苗的宠物，通过以下步骤：
     * 1. 收集所有接种疫苗记录的宠物ID
     * 2. 筛选出不在集合中的宠物
     *
     * @param scanner 输入流扫描器（未实际使用）
     */
    private static void unvaccinatedPetsAlert(Scanner scanner) {

        Set<String> vaccinatedPets = new HashSet<>();  ///一接种疫苗集合
        /// 遍历所有集合，如果医疗集合中有疫苗记录，就查询出来，将宠物id加到已接种疫苗集合
        for (MedicalRecord record : medicalRecords) {
            if (record.getType().equalsIgnoreCase("疫苗")) {
                vaccinatedPets.add(record.getPetId());
            }
        }

        /// 未接种疫苗集合
        List<Pet> unvaccinated = new ArrayList<>();
        /// 遍历宠物集合，如果已接种疫苗集合中不存在当前宠物的id，就将宠物加到未接种疫苗集合
        for (Pet pet : pets) {
            if (!vaccinatedPets.contains(pet.getPetId())) { ///不存在返回false，取反就是true
                unvaccinated.add(pet);
            }
        }

        /// 如果未接种疫苗集合为空，就显示第一个，否则第二个
        if (unvaccinated.isEmpty()) {
            System.out.println("所有宠物均已接种疫苗");
        } else {
            System.out.println("未接种疫苗的宠物:");
            for (Pet pet : unvaccinated) {
                System.out.println(pet);
            }
        }
    }

    /**
     * 根据ID查找宠物的方法
     * 搜索所有宠物列表进行匹配
     * @param petId 要查找的宠物ID
     * @return 匹配的Pet对象或null
     */
    private static Pet findPetById(String petId) {
        for (Pet pet : pets) {
            if (pet.getPetId().equals(petId)) {
                return pet;
            }
        }
        return null;
    }



    /**
     * 验证宠物ID格式
     * 验证正则表达式：P\d{3}
     */
    public static boolean isValidPetId(String id) {
        return id.matches("p\\d{3}");
    }

    /**
     * 验证主人ID格式
     * 验证正则表达式：O\d{3}
     */
    public static boolean isValidOwnerId(String id) {
        return id.matches("o\\d{3}");
    }

    /**
     * 验证电话号码格式
     * 验证正则表达式：\d{11}
     */
    public static boolean isValidPhone(String phone) {
        return phone.matches("\\d{11}");
    }
}